// #include <PcapLiveDeviceList.h>
#include <PfRingDeviceList.h>
#include <Packet.h>
#include <iostream>
#include "headers/packet_handler.h"
#include <IPv4Layer.h>
#include <PcapFileDevice.h>
#include <chrono>
#include <signal.h>

void init_db(std::string table_prefix)
{
	// especially carefully to edit table names as there are many of them.

	// 如果不存在表,就创建表
    Client client(ClientOptions().SetHost("localhost"));
	// client.Execute(R"(CREATE DATABASE IF NOT EXISTS default)");
	client.Execute(R"(CREATE TABLE IF NOT EXISTS default.)"+table_prefix+R"(_packets (insertTime DateTime DEFAULT now(),hashVal UInt32,packetLen Int32,tvSec UInt32,tvNsec UInt32,srcIp String,
						dstIp String,ttl UInt8,tos UInt8,id UInt16,offset UInt16,protocolIP  UInt8,protocol UInt8,lenLoad UInt16,srcPort UInt16,
						dstPort UInt16,ackNum UInt32,seqNum UInt32,flag UInt16,window UInt16,lenUdp UInt16,icmpType UInt8,icmpCode UInt8,) 
				ENGINE = MergeTree()
				ORDER BY (hashVal,insertTime)
				TTL insertTime + INTERVAL 2 HOUR DELETE
    )");

	// 创建一个表,用来对结果进行聚合，存储default.packets表中每个hashVal的最近更新时间，并统计每个hashVal的行数(packet_count),
	client.Execute(R"(
		CREATE TABLE IF NOT EXISTS default.)"+table_prefix+R"(_hashVal_summary(
			hashVal UInt32,
			packet_count AggregateFunction(count, Nullable(Int32)),
		)
		ENGINE = AggregatingMergeTree()
		ORDER BY hashVal;
	)");

	// 创建一个物化视图hashVal_mv，存储default.packets表，统计每个hashVal的行数(packet_count),
	client.Execute(R"(
		CREATE MATERIALIZED VIEW IF NOT EXISTS default.)"+table_prefix+R"(_hashVal_mv TO default.)"+table_prefix+R"(_hashVal_summary
		AS SELECT
			hashVal,
			countState() as packet_count,
		FROM default.)"+table_prefix+R"(_packets
		GROUP BY hashVal;
	)");
}


int main(int argc, char *argv[])
{
	if (argc!=3) //pcap path , db index name
	{
		std::cerr <<"params count wrong"<<std::endl;
		return -1; 
	}

	// 打开pcap文件，获得reader
	pcpp::PcapFileReaderDevice reader(argv[1]);
	if (!reader.open())
	{
		std::cerr << "Error opening the pcap file" << std::endl;
		return -1; 
	}

	init_db(argv[2]);
	
	// 判断能否读包
	pcpp::RawPacket rawPacket;
	if (!reader.getNextPacket(rawPacket))
	{
		std::cerr << "Couldn't read the first packet in the file" << std::endl;
		return -1;
	}

	packet_handler* packetHandler = new packet_handler(argv[2]);

	std::cout<<"successful running ...等待处理..."<<std::endl;
	long long pac_count=0;
	while(reader.getNextPacket(rawPacket))
	{
		// 解析数据包
		pcpp::Packet parsedPacket(&rawPacket);

		// verify the packet is IPv4
		if (parsedPacket.isPacketOfType(pcpp::IPv4))
		{	
			// 准备搜集算子
			packetHandler->handle_packet(&parsedPacket);
			pac_count++;
		}
	}
	std::cout<<"pcap finished.Totol packet counts:"<<pac_count<<std::endl;
	reader.close();
	delete packetHandler;
	return 0;
}